package com.blacktea.es.service.strategy;

import com.blacktea.es.entites.common.ESConst;
import com.blacktea.es.entites.dto.PageRequest;
import com.blacktea.es.entites.dto.RequestScrollPage;
import com.blacktea.es.util.AssertUtil;
import com.blacktea.es.util.ESUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.*;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


@Service("scrollPageStrategy")
@RequiredArgsConstructor
@Slf4j
public class ScrollPageStrategyImpl<T> implements ESRequestPageStrategy<T> {

    private final RestHighLevelClient restHighLevelClient;
    @Value("${spring.elasticsearch.log.level}")
    private int level;

    @Override
    public List<T> list(Class<T> var1, SearchRequest searchRequest, PageRequest pageRequest) throws IOException {
        List<T> resultList = new ArrayList<>();
        RequestScrollPage requestScrollPage = (RequestScrollPage) pageRequest;
        //失效时间
        TimeValue scrollTimeValue = requestScrollPage.getScrollTimeValue();
        if (null == scrollTimeValue){
            AssertUtil.fail(ESConst.ESErrorCodeEnum.PAGE_SCROLL_TIMEVALUE_NOT_NULL);
        }
        Scroll scroll = new Scroll(scrollTimeValue);
        //封存快照
        searchRequest.scroll(scroll);
        SearchSourceBuilder searchSourceBuilder = searchRequest.source();
        searchSourceBuilder.size(pageRequest.getLimit());
        ESUtil.esLog(ESConst.ESLogLevelEnum.getByLevel(level),searchRequest);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        String scrollId;
        do {
            resultList.addAll(ESUtil.searchResponseToList(searchResponse, var1));
            //每次循环完后取得scrollId,用于记录下次将从这个游标开始取数
            scrollId = searchResponse.getScrollId();
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(scroll);
            ESUtil.esLog(ESConst.ESLogLevelEnum.getByLevel(level),scrollRequest);
            //进行下次查询
            searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
        } while (searchResponse.getHits().getHits().length != 0);
        //清除滚屏
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        //也可以选择setScrollIds()将多个scrollId一起使用
        clearScrollRequest.addScrollId(scrollId);
        ESUtil.esLog(ESConst.ESLogLevelEnum.getByLevel(level),clearScrollRequest);
        ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
        if (!clearScrollResponse.isSucceeded()){
            log.error("scroll清除失败,scrollId={}",scrollId);
        }
        return resultList;
    }

}
